-------------------------------------------------------------------------------
-- Design Name: hw3_top.vhd
-- Author: Aaron Baxter
-- Design Overview: Simple Calculator

-- Synthesis Results: Warning about unused flip flops being trimmed 

-- Utilization:
-- Flip Flops: 68
-- LUTs: 221
-- Slices: 144

-- Functionality: Works as specified
-------------------------------------------------------------------------------

library IEEE;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_1164.ALL;

entity hw4_top is
port (
	clk : in std_logic;
	sliderswitches : in std_logic_vector(7 downto 0);
	pushbuttons : in std_logic_vector(3 downto 0);
	Led : out std_logic_vector(7 downto 0);
	seg7 : out std_logic_vector(7 downto 0);
	anodes : out std_logic_vector(3 downto 0)
);
end hw4_top;

architecture Behavioral of hw4_top is

	constant SHFTL 	: unsigned := "0000";
	constant SHFTR 	: unsigned := "0001";
	constant BTC 	: unsigned := "0010";
	constant BTS 	: unsigned := "0011";
	constant ROTL 	: unsigned := "0100";
	constant ROTR 	: unsigned := "0101";
	constant MUL 	: unsigned := "0110";
	constant ADDP 	: unsigned := "0111";
	constant ADD 	: unsigned := "1000";
	constant SUB 	: unsigned := "1001";
	constant PAR4 	: unsigned := "1010";
	constant NOP 	: unsigned := "1011";
	constant MAXAB 	: unsigned := "1100";
	constant BOOL 	: unsigned := "1101";
	
	COMPONENT seg_muxer
	PORT(
		clk : IN std_logic;
		rst : IN std_logic;
		hex1 : IN unsigned(3 downto 0);
		hex2 : IN unsigned(3 downto 0);          
		anodes : OUT std_logic_vector(3 downto 0);
		seg7 : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;

	signal rst 	: std_logic;
	signal btn_count 		: integer;

	signal data_in 	: std_logic_vector(7 downto 0);
	signal btns 	: std_logic_vector(3 downto 0);
	
	signal count 		: integer;
	signal clk_one_khz 	: std_logic;

	signal cur_but 	: integer;
	signal prev_but 	: integer;
	signal test_count 	: integer;
	signal hex1_out : unsigned (3 downto 0);
	signal hex2_out : unsigned (3 downto 0);

	signal opa : unsigned (3 downto 0);
	signal opb : unsigned (3 downto 0);
	signal operator : unsigned (7 downto 0);
	signal shift : integer;

	signal hex_tmp : unsigned (7 downto 0);
	signal op_boolean : unsigned (2 downto 0);
	
begin
	rst <= pushbuttons (3);

	Led(7 downto 4) 	<= std_logic_vector(opb);				-- light the right most seven segment
	Led(3 downto 0) 	<= std_logic_vector(opa);				-- light the right most seven segment
	
	shift <= to_integer(operator (1 downto 0));
	op_boolean <= (operator (2 downto 0));
	

		
	seg_muxer_uut: seg_muxer PORT MAP(
		clk => clk_one_khz,
		rst => rst,
		hex1 => hex_tmp(3 downto 0),
		hex2 => hex_tmp(7 downto 4),
		anodes => anodes,
		seg7 => seg7
	);	
	
	
	process (clk,rst)
		variable parity 	: std_logic;

	begin
		if rst = '1' then
			cur_but <= 0;
			prev_but <= 0;
			parity := '0';
			opa <= "0000";
			opb <= "0000";
			operator <= "00000000";
			hex_tmp <= "00000000";
			hex1_out <= "0000";
			hex2_out <= "0000";
		elsif rising_edge(clk) then
		
		
			if btns(0) = '1' then
				cur_but <= 1;
				
			elsif btns(1) = '1' then
				cur_but <= 2;
			
			elsif btns(2) = '1' then
				cur_but <= 3;
			
			
			
			end if;
			
			if (cur_but = prev_but) then 	--no button change
				
			else							--button changed
				prev_but <= cur_but;
				
				
				if (cur_but = 1) then 		--store sliders as values
					opa <= unsigned(sliderswitches (3 downto 0));
					opb <= unsigned(sliderswitches (7 downto 4));
					--hex_tmp <= "01110111";
					hex_tmp(7 downto 4) <= unsigned(sliderswitches (7 downto 4));
					hex_tmp(3 downto 0) <= unsigned(sliderswitches (3 downto 0));
				elsif (cur_but = 2) then	--store sliders as operator
					operator <= unsigned(sliderswitches (7 downto 0));
					hex_tmp <= unsigned(sliderswitches (7 downto 0));
				elsif (cur_but = 3) then	--compute result
					
					case operator(7 downto 4) is
						when SHFTL =>
							hex_tmp(3 downto 0) <= opa sll shift;
							
						when SHFTR =>
							hex_tmp(3 downto 0) <= opa srl shift;
							
						when BTC =>
							hex_tmp(3 downto 0) <= opa;
							hex_tmp(3 downto 0)(shift) <= '0';
							
						when BTS =>
							hex_tmp(3 downto 0) <= opa;
							hex_tmp(3 downto 0)(shift) <= '1';
							
						when ROTL =>
							hex_tmp(3 downto 0) <= opa rol shift;
							
						when ROTR =>
							hex_tmp(3 downto 0) <= opa ror shift;
							
						when MUL =>
							hex_tmp <= opa * opb;
							
						when ADDP =>
							hex_tmp <= opa + hex_tmp;
							
						when ADD =>
							hex_tmp <= opa + opb;
							
						when SUB =>
							hex_tmp <= opb - opa;

						when BOOL =>
						
							case op_boolean is
								when "000" =>
									hex_tmp(3 downto 0) <= not opa;
									hex_tmp(7 downto 4) <= "0000";
								when "001" =>
									hex_tmp(3 downto 0) <= opa and opb;
									hex_tmp(7 downto 4) <= "0000";
								when "010" =>
									hex_tmp(3 downto 0) <= opa or opb;
									hex_tmp(7 downto 4) <= "0000";
								when "011" =>
									hex_tmp(3 downto 0) <= opa XOR opb;
									hex_tmp(7 downto 4) <= "0000";
								when "100" =>
									hex_tmp(3 downto 0) <= opa NAND opb;
									hex_tmp(7 downto 4) <= "0000";
								when "101" =>
									hex_tmp(3 downto 0) <= opa NOR opb;
									hex_tmp(7 downto 4) <= "0000";
								when "110" =>
									hex_tmp(3 downto 0) <= opa XNOR opb;
									hex_tmp(7 downto 4) <= "0000";
								when others =>
									--
							end case;
						when PAR4 =>
							for I in opa'reverse_range loop
								if (opa(I) = '1') then
									parity := not parity;
								end if;
									
							end loop;
							hex_tmp(0) <= parity;
							hex_tmp(7 downto 1) <= "0000000";
							parity := '0';
							
						when MAXAB =>
							if (opa > opb) then
								hex_tmp(3 downto 0) <= opa ;	
							else
								hex_tmp(3 downto 0) <= opb ;	
							end if;
											
						
						when others =>
							--
					end case;

				end if;
				
			end if;
			
		end if;
	end process;

	
	--clock gate down to 1khz
	process (clk,rst)
	begin
		if rst = '1' then
			count			<= 0;
			clk_one_khz		<= '0';
		elsif rising_edge(clk) then
			if count = 50000 then
				clk_one_khz	<= not clk_one_khz;
				count	<= 0;
			else
				count	<= count + 1;
			end if;
		end if;
	end process;
	
	
	--button debounce
	process (clk_one_khz,rst)
	begin
		if rst = '1' then
			btns			<= "0000";
		elsif rising_edge(clk_one_khz) then
		
			if (pushbuttons = "0000") then
				btns			<= "0000";
			else
				btns <= pushbuttons;
			end if;
	
		end if;
	end process;
	
	
	
end Behavioral;



-----------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity seg_decoder is
    Port ( 
			dec_in 	: in  STD_LOGIC_VECTOR (3 downto 0);
			seg 	: out  STD_LOGIC_VECTOR (6 downto 0)
		);
end seg_decoder;

architecture Behavioral of seg_decoder is
begin
	-- 3 input to segment mapping (0-7)
	with dec_in select
		seg	<= 		"1000000" when "0000",
					"1111001" when "0001",
					"0100100" when "0010",
					"0110000" when "0011",
					"0011001" when "0100",
					"0010010" when "0101",
					"0000010" when "0110",
					"1111000" when "0111",
					"0000000" when "1000",
					
					"0011000" when "1001",
					"0001000" when "1010",
					"0000011" when "1011",
					"0100111" when "1100",
					"0100001" when "1101",
					"0000110" when "1110",
					"0001110" when "1111",
					"0000000" when others;


end Behavioral;

-----------------------------------------------
library IEEE;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_1164.ALL;

entity seg_muxer is
    Port ( 
			clk 	: in  STD_LOGIC;
			rst 	: in  STD_LOGIC;
			hex1 	: in  unsigned (3 downto 0);
			hex2 	: in  unsigned (3 downto 0);
			anodes 	: out  STD_LOGIC_VECTOR (3 downto 0);
			seg7 	: out  STD_LOGIC_VECTOR (7 downto 0)
		);
end seg_muxer;

architecture Behavioral of seg_muxer is

	COMPONENT seg_decoder
	PORT(
		dec_in : IN std_logic_vector(3 downto 0);          
		seg : OUT std_logic_vector(6 downto 0)
		);
	END COMPONENT;


	signal count : STD_LOGIC ;
	signal hex_internal : STD_LOGIC_VECTOR (3 downto 0);
begin



	Inst_seg_decoder: seg_decoder PORT MAP(
		dec_in => hex_internal(3 downto 0),
		seg =>  seg7(6 downto 0)  
	);

	process (clk,rst)
	begin
		if rst = '1' then
			count <= '0';
		elsif rising_edge(clk) then
		
			if (count = '1') then
				hex_internal 	<= std_logic_vector(hex1);
				anodes			<= "1110";
			else
				hex_internal 	<= std_logic_vector(hex2);
				anodes			<= "1101";
			end if;
			
			
			count <= not count;
	
		end if;
	end process;






end Behavioral;





